package core;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RefineryUtilities;



public class Oscilloscope extends UnitAbstract implements ActionListener
{

	private static final long serialVersionUID = 6714670741505892279L;
	private transient XYSeries series1;
	private transient XYSeries series2;
	private transient JTextField itemsCountSeries1Field;
	private transient JTextField itemsCountSeries2Field;
	
	private transient JTextField rangeX;
	private transient JTextField rangeY;
	
	private JFreeChart chart;
	private XYSeriesCollection dataset1;
	
	private final int DEFAULT_MAX_ITEM_COUNT_A = 1000;
	private final int DEFAULT_MAX_ITEM_COUNT_B = 1000;
	
	private final String FIRST_SLOT_NAME = "A";
	private final String SECOND_SLOT_NAME = "B";
	
	ValueAxis axis;
	
	private transient JButton settingsButton;
	
    private JButton button;
    private boolean mStarted = false;
    private transient XYPlot plot;
    private transient JFrame frame;
	
	public Oscilloscope()
	{
		init();
	}
	
	private void init()
	{
		// init inputs
		inputs = new String[]
		{
				FIRST_SLOT_NAME,
				SECOND_SLOT_NAME
		};
	}
	
	private void initFormValues()
	{
		button = new JButton("Start");
		settingsButton = new JButton("Aktualizuj");
		
		itemsCountSeries1Field = new JTextField("1000");
        itemsCountSeries2Field = new JTextField("1000");
        rangeX = new JTextField("-1.1");
        rangeY = new JTextField("1.1");
	}
	
	private void showFrame()
	{
	    RefineryUtilities.centerFrameOnScreen(frame);
	    frame.setVisible(true);
	}
	
	private void prepareColection()
	{
		series1 = new XYSeries("1");
		series2 = new XYSeries("2");
		series1.setMaximumItemCount(DEFAULT_MAX_ITEM_COUNT_A);
		series2.setMaximumItemCount(DEFAULT_MAX_ITEM_COUNT_B);
	}
	
	public JFrame aFrame(String title)
	{
		JFrame ret = new JFrame(title);
		
		initFormValues();
		
        dataset1 = new XYSeriesCollection();
        prepareColection();
        dataset1.addSeries(series1);
        dataset1.addSeries(series2);
        
        chart = ChartFactory.createXYLineChart(
                "Oscilloscope", 
                "Time", 
                "Value",
                null, 
                PlotOrientation.VERTICAL,
                true, 
                true, 
                false
            );
        
        plot = chart.getXYPlot();
        
        plot.setDataset(0, dataset1);
        
        axis = plot.getDomainAxis();
        
        axis.setAutoRange(true);
        axis.setFixedAutoRange(0.1);  // 1 seconds
        axis = plot.getRangeAxis();
        axis.setRange(-1.1, 1.1); 
        
        axis = plot.getRangeAxis();
//      axis.setAutoRange(true);
        axis.setFixedAutoRange(0.0001);
        axis.setRange(-1.1, 1.1);
        
        // main ui panel
        JPanel content = new JPanel(new BorderLayout());
        
        // main chart panel
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        
        // settings panel
        JPanel settingsPanel = new JPanel(new BorderLayout());
        settingsPanel.setName("Settings");
        settingsPanel.setBorder(BorderFactory.createLineBorder (Color.blue, 1));
		
		JPanel options = new JPanel();
		options.setLayout(new GridLayout(4,2));
		
		options.add(new Label("Ilość elementów w serii 1"));
		options.add(itemsCountSeries1Field);
		options.add(new Label("Ilość elementów w serii 2"));
		options.add(itemsCountSeries2Field);
		
		options.add(new Label("Range X"));
		options.add(rangeX);
		options.add(new Label("Range Y"));
		options.add(rangeY);
		
        button.setText("Start");
        mStarted = true;
        
        button.addActionListener(this);      

        settingsButton.addActionListener(new ActionListener() 
        {
			@Override
			public void actionPerformed(ActionEvent e) 
			{
				
				series1.setMaximumItemCount(Integer.parseInt(itemsCountSeries1Field.getText()));
				series2.setMaximumItemCount(Integer.parseInt(itemsCountSeries2Field.getText()));
				double rangeXD = Double.parseDouble(rangeX.getText());
				double rangeYD = Double.parseDouble(rangeY.getText());
				axis.setRange(rangeXD, rangeYD);
			}
		});
        
        settingsPanel.add(settingsButton,BorderLayout.SOUTH);
        settingsPanel.add(options, BorderLayout.WEST);
        
        content.add(settingsPanel, BorderLayout.WEST);
        content.add(chartPanel);
        
        content.add(button, BorderLayout.SOUTH);
        ret.setContentPane(content);
        return ret;
	}


	public void actionPerformed(final ActionEvent e) 
	{
		MyTimer.getInstance().changeState();
		
        if(mStarted == true && button != null )
        {
        	button.setText("Stop");
        	mStarted = false;
        }
        else if(mStarted == false)
        {
        	button.setText("Start");
        	mStarted = true;
        }
    }
    
	public void read(DataPackage dataPack, String tPort) 
	{
		XYSeries series;

		if(tPort.equals(inputs[0]))
		{
			series = series1;
		}
		else
		{
			series = series2;
		}
		
		int resample = 0;
		if(frame != null)
		{
			resample = (int) (dataPack.data.length/((dataPack.duration/0.1)*frame.getWidth()*2));
		}
		
		for(int i=0; i+resample<dataPack.data.length; i++)
		{
			if(resample>1)
			{
				double mean = 0;
				for(int j=0; j<resample; j++)
				{
					mean += dataPack.data[i+j];
				}
				mean /= resample;
				
				series.add(dataPack.timeStart+(i+resample/2)/dataPack.sampleRate, mean);
				i=i+resample-1;
				
			}
			else
			{
				series.add(dataPack.timeStart+i/dataPack.sampleRate,  dataPack.data[i]);
			}
			
//			double tempY = series.getY(i).doubleValue();
//			
//			if(series.getMaxY() >= axis.getRange().getUpperBound() || series.getMinY() <= axis.getRange().getLowerBound())
//			{
//				axis.setRange(series.getMinY(), series.getMaxX());
//				plot.setRangeAxis(axis);
//			}
		}
		

		return;
	}
	
	public void connect(UnitConnection ui) 
	{

	}
	
	@Override
	public void disconnect(UnitConnection ui) 
	{
		// TODO Auto-generated method stub
		
	}
	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
	{
		in.defaultReadObject();
		frame = aFrame("Oscilloscope");
		frame.pack();
	}
	
	@Override
	public String toString() 
	{
		return "Oscyloskop";
	}

	@Override
	public JFrame getFrame() 
	{
		return frame;
	}

}